# include "widgetlienzogtkmm.h"

Gdk::Color black = Gdk::Color("black");

Gdk::Color white = Gdk::Color("white");

Gdk::Color red = Gdk::Color("red");

Gdk::Color blue = Gdk::Color("blue");

WidgetLienzogtkmm::WidgetLienzogtkmm(xmlref_t& ref)
{
	lienzo = new Lienzo();
	
	finPoligono = false;
	
	temp = NULL;
	
	accion = seleccionar;
	
	nombre = "guardado.paint";
	
	//Botones
	
	ref->get_widget("botonSeleccionar", BSeleccionar);
	
	BSeleccionar->signal_clicked().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::setAccionS));
	
	ref->get_widget("botonPunto", BPunto);
	
	BPunto->signal_clicked().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::setAccionP));
	
	ref->get_widget("botonLinea", BLinea);
	
	BLinea->signal_clicked().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::setAccionL));
	
	ref->get_widget("botonRectangulo", BRectangulo);
	
	BRectangulo->signal_clicked().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::setAccionR));
	
	ref->get_widget("botonCirculo", BCirculo);
	
	BCirculo->signal_clicked().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::setAccionC));
	
	ref->get_widget("botonPoligono", BPoligono);
	
	BPoligono->signal_clicked().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::setAccionPol));
	
	ref->get_widget("botonCopiar", BCopiar);
	
	BCopiar->signal_clicked().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::copiaEvento));
	
	ref->get_widget("botonCortar", BCortar);
	
	BCortar->signal_clicked().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::cortaEvento));
	
	ref->get_widget("botonPegar", BPegar);
	
	BPegar->signal_clicked().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::pegaEvento));
	
	ref->get_widget("botonEliminar", BEliminar);
	
	BEliminar->signal_clicked().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::borraEvento));
	
	ref->get_widget("botonAgrupar", BAgrupar);
	
	BAgrupar->signal_clicked().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::agrupaEvento));
	
	ref->get_widget("botonDesagrupar", BDesagrupar);
	
	BDesagrupar->signal_clicked().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::desagrupaEvento));
	
	ref->get_widget("menuNuevo", MNuevo);
	
	MNuevo->signal_activate().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::Nuevo));
	
	ref->get_widget("menuAbrir", MAbrir);
	
	MAbrir->signal_activate().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::Abrir));
	
	ref->get_widget("menuGuardar", MGuardar);
	
	MGuardar->signal_activate().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::Guardar));
	
	ref->get_widget("menuGuardarComo", MGuardarComo);
	
	MGuardarComo->signal_activate().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::GuardarComo));
	
	ref->get_widget("menuCopiar", MCopiar);
	
	MCopiar->signal_activate().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::copiaEvento));
	
	ref->get_widget("menuCortar", MCortar);
	
	MCortar->signal_activate().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::cortaEvento));
	
	ref->get_widget("menuPegar", MPegar);
	
	MPegar->signal_activate().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::pegaEvento));
	
	ref->get_widget("menuRehacer", MRehacer);
	
	MRehacer->signal_activate().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::rehacerEvento));
	
	ref->get_widget("menuDeshacer", MDeshacer);
	
	MDeshacer->signal_activate().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::deshacerEvento));
	
	ref->get_widget("aboutdialog1", MAbout);
	
	ref->connect_clicked("menuAbout", sigc::mem_fun (*this, &WidgetLienzogtkmm::mostrarAbout));
	
	ref->get_widget("sliderR", sliderR);
	
	sliderR->signal_value_changed().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::colorBoton));
	
	ref->get_widget("sliderG", sliderG);
	
	sliderG->signal_value_changed().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::colorBoton));
	
	ref->get_widget("sliderB", sliderB);
	
	sliderB->signal_value_changed().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::colorBoton));
	
	ref->get_widget("botonCambiaColor", botonCambiaColor);
	
	botonCambiaColor->signal_clicked().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::cambiarColor));
	
	colorBoton();
	
	//Lienzo
	
	ref->get_widget("drawArea", drawArea);
	
	drawArea->add_events(Gdk::BUTTON_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK );
	
	drawArea->signal_button_press_event().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::click));
	
	drawArea->signal_motion_notify_event().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::mover));
	
	drawArea->signal_button_release_event().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::soltar));	
	
	drawArea->signal_realize().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::iniciar));
	
	drawArea->signal_expose_event().connect(sigc::mem_fun(*this, &WidgetLienzogtkmm::pintar));
}

void
WidgetLienzogtkmm::colorBoton()
{
	Gdk::Color c;
	
	c.set_red(sliderR->get_value() * 256);
	
	c.set_green(sliderG->get_value() * 256);
	
	c.set_blue(sliderB->get_value() * 256);
	
	botonCambiaColor->modify_bg(Gtk::STATE_NORMAL , c);
	
	botonCambiaColor->modify_bg(Gtk::STATE_ACTIVE , c);
	
	botonCambiaColor->modify_bg(Gtk::STATE_PRELIGHT , c);
	
	botonCambiaColor->modify_bg(Gtk::STATE_SELECTED  , c);
}

void
WidgetLienzogtkmm::mostrarAbout()
{
	MAbout->run ();
	
	MAbout->hide ();	
}

void
WidgetLienzogtkmm::iniciar()
{
	Glib::RefPtr<Gdk::Colormap> colormap = drawArea->get_default_colormap();
	
	colormap->alloc_color(white);
	
	colormap->alloc_color(black);
	
	colormap->alloc_color(red);
	
	colormap->alloc_color(blue);
	
	dw = drawArea->get_window();
	
	dw->set_background(white);
	
	gc = Gdk::GC::create(dw);
	
	gc->set_foreground(black);
}

void 
WidgetLienzogtkmm::Abrir()
{
	Gtk::FileChooserDialog fcd("Selecciona un archivo");
	
	fcd.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
	
	fcd.add_button("Ok", Gtk::RESPONSE_OK);
	
	int result = fcd.run();
	
	if (result == Gtk::RESPONSE_OK)
	{
		lienzo->leerFichero(fcd.get_filename());
	}
}

void 
WidgetLienzogtkmm::Guardar()
{
	ofstream fichero;
	
	fichero.open(nombre.c_str(), ios::out);
	
	if (fichero.is_open())
	{
		fichero << lienzo->Texto();
	}
	
	fichero.close();
}

void 
WidgetLienzogtkmm::GuardarComo()
{
	Gtk::FileChooserDialog fcd("Selecciona un archivo");
	
	fcd.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
	
	fcd.add_button("Ok", Gtk::RESPONSE_OK);
	
	int result = fcd.run();
	
	if (result == Gtk::RESPONSE_OK)
	{
		nombre = fcd.get_filename();
		
		Guardar();
	}
}

bool
WidgetLienzogtkmm::click(GdkEventButton* event)
{
	anterior.setX(event->x);
	
	anterior.setY(event->y);
	
	if (!seleccionadas.empty() && !pinchaDentro(event->x, event->y))
	{
		seleccionadas.clear();
	}	
	
	return false;
}

bool
WidgetLienzogtkmm::mover (GdkEventMotion* actual)
{
	Figura* f;
	
	list<Figura*> aux;

	if (accion == poligono && finPoligono)
	{
		Punto a (temp->getPuntos().back().getX(), temp->getPuntos().back().getY());
		
		Punto b (actual->x, actual->y);
		
		Punto c (temp->getPuntos().front().getX(), temp->getPuntos().front().getY());	
			
		f= new Linea(a,b);
		
		pintaAccion = f->pintar();
		
		f = new Linea(b,c);
		
		aux = f->pintar();
		
		pintaAccion.splice(pintaAccion.end(), aux);
		
		delete f;		
	}

	else if (accion == linea || accion == poligono)
	{
		Punto a (anterior.getX(), anterior.getY());
		
		Punto b (actual->x, actual->y);
					
		f= new Linea(a,b);
		
		pintaAccion = f->pintar();
		
		delete f;
	}
	
	else if (accion == seleccionar)
	{
		if (seleccionadas.empty())
		{
			Punto a (anterior.getX(), anterior.getY());
			
			Punto b (actual->x, actual->y);
			
			lienzo->normalizaPuntos(a,b);
			
			f = new Rectangulo(a,b);

			pintaAccion = f->pintar();
			
			delete f;			
		}
		
		else if ((actual->state & GDK_BUTTON3_MASK ) != 0 )
		{
			pintaAccion.clear();
			
			for (list<Figura*>::iterator i = seleccionadas.begin(); i != seleccionadas.end(); i++)
			{
				f = (*i)->clonar();
				
				if (dynamic_cast <Rectangulo*> (f))
				{
					((Rectangulo*)f)->redimensionar2(actual->x-anterior.getX(), actual->y-anterior.getY());
				}
				
				else
				{
					f->redimensionar((actual->x-anterior.getX()), (actual->y-anterior.getY()));
				}
				
				aux = f->pintar();
				
				pintaAccion.splice(pintaAccion.end(), aux);
				
				delete f;
			}			
		}
		
		else
		{
			pintaAccion.clear();
			
			for (list<Figura*>::iterator i = seleccionadas.begin(); i != seleccionadas.end(); i++)
			{
				f = (*i)->clonar();
				
				f->trasladar((actual->x-anterior.getX()), (actual->y-anterior.getY()));
				
				aux = f->pintar();
				
				pintaAccion.splice(pintaAccion.end(), aux);
				
				delete f;
			}				
		} 
	}
	
	if (accion == rectangulo)
	{
		Punto a (anterior.getX(), anterior.getY());
		
		Punto b (actual->x, actual->y);
		
		lienzo->normalizaPuntos(a,b);
		
		f= new Rectangulo(a,b);

		pintaAccion = f->pintar();
		
		delete f;			
	}
	
	else if (accion == circulo)
	{
		Punto a (anterior.getX(), anterior.getY());
		
		Punto b (actual->x, actual->y);
		
		float dif = sqrt((b.getX() - a.getX())*(b.getX() - a.getX()) + (b.getY() - a.getY())*(b.getY() - a.getY()));
		
		f= new Circulo(a, dif);
		
		pintaAccion = f->pintar();
		
		delete f;		
	}
	
	update();
	
	return false;
}

bool 
WidgetLienzogtkmm::soltar(GdkEventButton* e )
{
	Figura* f;
	
	Punto actual;
	
	list<Figura*> lista ;
	
	bool redim;
	
	actual.setX(e->x);
	
	actual.setY(e->y);
	
	switch (accion)
	{
		case punto: 
		{
			PuntoDibujo* p = new PuntoDibujo(Punto(anterior.getX(), anterior.getY()));
			
			p->setCR(sliderR->get_value());
			
			p->setCG(sliderG->get_value());
			
			p->setCB(sliderB->get_value());
			
			lienzo->anyadirFigura(p);
		}
		break;
		
		case linea: 
		{
			Punto a (anterior.getX(), anterior.getY());
			
			Punto b (actual.getX(), actual.getY());
			
			f= new Linea(a,b);
			
			f->setCR(sliderR->get_value());
			
			f->setCG(sliderG->get_value());
			
			f->setCB(sliderB->get_value());			
			
			lienzo->anyadirFigura(f);
		}
		break;
		
		case rectangulo:
		{
			Punto a (anterior.getX(), anterior.getY());
			
			Punto b (actual.getX(), actual.getY());
			
			lienzo->normalizaPuntos(a,b);
			
			f = new Rectangulo(a,b);
			
			f->setCR(sliderR->get_value());
			
			f->setCG(sliderG->get_value());
			
			f->setCB(sliderB->get_value());	
						
			lienzo->anyadirFigura(f);					
		}
		break;
		
		case circulo:
		{
			Punto a (anterior.getX(), anterior.getY());
			
			Punto b (actual.getX(), actual.getY());
			
			float dif = sqrt((b.getX() - a.getX())*(b.getX() - a.getX()) + (b.getY() - a.getY())*(b.getY() - a.getY()));
			
			f = new Circulo(a, dif);

			f->setCR(sliderR->get_value());
			
			f->setCG(sliderG->get_value());
			
			f->setCB(sliderB->get_value());	
						
			lienzo->anyadirFigura(f);
		}
		break;
		
		case poligono:
		{	
			primero = anterior;
			
			if (!finPoligono)
			{
				finPoligono = true;
				
				temp = new Poligono();
				
				temp->setCR(sliderR->get_value());
				
				temp->setCG(sliderG->get_value());
				
				temp->setCB(sliderB->get_value());					
				
				temp->addPunto(Punto(anterior.getX(), anterior.getY()));
				
				temp->addPunto(Punto(actual.getX(), actual.getY()));
			}
			
			else
			{
				temp->addPunto(Punto(actual.getX(), actual.getY()));
			}					
			
		}
		break;
		
		case seleccionar:
		{		
			if (anterior == actual)
			{
				seleccionadas.clear();
				
				f = lienzo->seleccionar(anterior.getX(), anterior.getY());
				
				if (f != NULL)
				{
					seleccionadas.push_back(f);
				}
			}
			
			else
			{
				if (seleccionadas.empty())
				{
					Punto a (anterior.getX(), anterior.getY());
					
					Punto b (actual.getX(), actual.getY());
					
					lienzo->normalizaPuntos(a,b);
					
					lista = lienzo->seleccionar(a, b);
									
					seleccionadas = lista;
				}
				
				else
				{
					if ((e->state & GDK_BUTTON3_MASK) != 0)
					{
						lienzo->redimensionar(seleccionadas, actual.getX()-anterior.getX(), actual.getY()-anterior.getY());
					}
					
					else 
					{
						lienzo->trasladar(seleccionadas, actual.getX()-anterior.getX(), actual.getY()-anterior.getY());
					}
				}
			}
		}
		break;
	}
	
	update();	
	
	return false;
}

bool
WidgetLienzogtkmm::pintar(GdkEventExpose * e)
{
	list<Figura*>l;
	
	Figura* f;
	
	dw->clear();
	
	if (!seleccionadas.empty())
	{
		gc->set_foreground(red);
		
		f = new Grupo();
		
		for (list<Figura*>::iterator i = seleccionadas.begin(); i != seleccionadas.end(); i++)
		{
			((Grupo*)f)->anyadirElemento(*i);
		}
		
		l = ((Grupo*)f)->getCaja().pintar();
		
		for (list<Figura*>::iterator i = l.begin(); i != l.end(); i++)
		{
			pintaFigura(*i, true);		
		}
		
		l.clear();
		
		delete f;
	}
	
	if (!pintaAccion.empty())
	{
		gc->set_foreground(blue);	
		
		for (list<Figura*>::iterator i = pintaAccion.begin(); i != pintaAccion.end(); i++)
		{
			pintaFigura(*i);
			
			delete *i;
		}
		
		pintaAccion.clear();		
	}
	
	l = lienzo->Pintar();
	
	if (temp != NULL)
	{
		list<Figura*>lAux = temp->pintar();
		
		l.splice(l.end(), lAux);
	}
	
	gc->set_foreground(black);
	
	for (list<Figura*>::iterator i = l.begin(); i != l.end(); i++)
	{
		pintaFigura(*i, false, true);
	}
		
	return false;
}

void
WidgetLienzogtkmm::pintaFigura (Figura* f, bool caja, bool color)
{
	int tamCaja = 0;
	
	Punto a;
	
	Punto b;
	
	if (caja)
	{
		tamCaja = 1;
	}
	
	else
	{
		tamCaja = 0;
	}
	
	if (color)
	{
		Gdk::Color c;
		
		c.set_red(f->getCR()*256);
		
		c.set_blue(f->getCB()*256);
		
		c.set_green(f->getCG()*256);
		
		gc->set_rgb_fg_color(c);
	}
	
	if (dynamic_cast<PuntoDibujo*> (f))
	{
		dw->draw_point(gc, (f)->infDer().getX(), (f)->infDer().getY());
	}
	
	if (dynamic_cast<Linea*>(f))
	{
		a.setX(((Linea*)f)->getA().getX() + tamCaja);
		
		a.setY(((Linea*)f)->getA().getY() + tamCaja);
		
		b.setX(((Linea*)f)->getB().getX() + tamCaja);
		
		b.setY(((Linea*)f)->getB().getY() + tamCaja);
		
		dw->draw_line(gc, a.getX(), a.getY(), b.getX(), b.getY());
	}
	
	else if (dynamic_cast<Circulo*>(f))
	{
		Punto supIzq;
		
		supIzq.setX( ((Circulo*)f)->getC().getX() - abs(((Circulo*)f)->getR()) );
		
		supIzq.setY( ((Circulo*)f)->getC().getY() - abs(((Circulo*)f)->getR()));
		
		int ancho = abs(((Circulo*)f)->getR() * 2);

		dw->draw_arc(gc, false, supIzq.getX(), supIzq.getY(), ancho, ancho, 0, 23040);
	}	
}

void 
WidgetLienzogtkmm::copiaEvento() 
{
	for (list<Figura*>::iterator i = portaPapeles.begin(); i != portaPapeles.end(); i++)
	{
		delete (*i);	
	}
	
	portaPapeles.clear();
	
	for (list<Figura*>::iterator i = seleccionadas.begin(); i != seleccionadas.end(); i++)
	{
		Figura* clon = (*i)->clonar();
		
		portaPapeles.push_back(clon);
	}
	
	actualizar();	
}

void 
WidgetLienzogtkmm::pegaEvento() 
{
	list<Figura*> aux;
	
	for (list<Figura*>::iterator i = portaPapeles.begin(); i != portaPapeles.end(); i++)
	{
		lienzo->anyadirFigura (*i);	
		
		aux.push_back((*i)->clonar());
	}
	
	portaPapeles = aux;
	
	actualizar();	
}

void 
WidgetLienzogtkmm::cortaEvento() 
{
	copiaEvento();
	
	for (list<Figura*>::iterator i = seleccionadas.begin(); i != seleccionadas.end(); i++)
	{
		lienzo->quitarFigura (*i);
	}
	
	seleccionadas.clear();
	
	actualizar();	
}

void 
WidgetLienzogtkmm::borraEvento() 
{
	for (list<Figura*>::iterator i = seleccionadas.begin(); i != seleccionadas.end(); i++)
	{
		lienzo->quitarFigura (*i);
	}
	
	seleccionadas.clear();
	
	actualizar();	
}

void 
WidgetLienzogtkmm::agrupaEvento() 
{
	if (!seleccionadas.empty()){ lienzo->agrupar(seleccionadas);};	
}

void 
WidgetLienzogtkmm::desagrupaEvento() 
{
	for (list<Figura*>::iterator i = seleccionadas.begin(); i != seleccionadas.end(); i++)
	{
		if (dynamic_cast <Grupo*>(*i))
		{
			lienzo->desagrupar((Grupo*)(*i));
		}
	}
	
	seleccionadas.clear();	
}

bool
WidgetLienzogtkmm::pinchaDentro(float x, float y)
{
	Grupo g;

	for (list<Figura*>::iterator i = seleccionadas.begin(); i != seleccionadas.end(); i++)
	{
		g.anyadirElemento(*i);
	}
	
	return g.getCaja().seleccionar(x, y);
}

void
WidgetLienzogtkmm::cambiarColor ()
{
	for (list<Figura*>::iterator i = seleccionadas.begin(); i != seleccionadas.end(); i++)
	{
		(*i)->setCR(sliderR->get_value());
		
		(*i)->setCG(sliderG->get_value());
		
		(*i)->setCB(sliderB->get_value());
	}
	
	update();
}
